﻿/*
 * Copyright © 2020, Wuxi Safover Intelligent Technology Co., Ltd. All rights reserved.
 * 
 * 无锡安永智能科技有限公司版权所有，未经许可，不得用于商业用途
 * 
 * Visit: https://www.safover.com/ 
 */

using System;
using Safover.LidarCollector.Models;
using Safover.LidarCollector.Config;

namespace Safover.LidarCollector.Core
{

    public abstract class GpsLocatorDevice : SerialPortDevice, IGpsLocatorControllable, IGpsLocator
    {
        public double DefaultLatitude { get; set; }
        public double DefaultLongitude { get; set; }
        public double DefaultAltitude { get; set; }

        private BaseGpsLocatorController CurrentController { get; set; }
        private BaseGpsLocatorController ClosedStateController { get; }
        private BaseGpsLocatorController OpenedStateController { get; }


        protected double? RealLongitude { get; set; }

        protected double? RealLatitude { get; set; }

        protected double? RealAltitude { get; set; }

        public double Latitude => RealLatitude == null ? DefaultLatitude : (double)RealLatitude;

        public double Longitude => RealLongitude == null ? DefaultLongitude : (double)RealLongitude;

        public double Altitude => RealAltitude == null ? DefaultAltitude : (double)RealAltitude;

        public long? UtcTimestamp { get; protected set; }


        public bool CanOpen => CurrentController.CanOpen;

        public bool CanClose => CurrentController.CanClose;

        public bool CanOperate => CurrentController.CanOperate;


        public GpsLocatorStatus Status => CurrentController.GpsLocatorStatus;

        public abstract GpsInformation ObtainGpsInformation();

        public GpsLocatorDevice()
        {
            ClosedStateController = new GpsLocatorClosedStateController(this);

            OpenedStateController = new GpsLocatorOpenedStateController(this);

            CurrentController = ClosedStateController;
        }

        protected override void ResetSerialPortParameters()
        {
            PortName = RuntimeConfigManager.Instance.GPSConfig.PortName;
            BaudRate = RuntimeConfigManager.Instance.GPSConfig.BaudRate;
        }

        internal void SetStatus(GpsLocatorStatus status)
        {
            switch (status)
            {
                case GpsLocatorStatus.Closed:
                    CurrentController = ClosedStateController;
                    break;
                case GpsLocatorStatus.Opened:
                    CurrentController = OpenedStateController;
                    break;
                default:
                    throw new InvalidOperationException($"Illegal device status = [{status}].");
            }
        }

        bool IGpsLocatorControllable.TryOpen()
        {
            return CurrentController.CanOpen ? CurrentController.TryOpen() : false;
        }

        bool IGpsLocatorControllable.TryClose()
        {
            return CurrentController.CanClose ? CurrentController.TryClose() : false;
        }

        GpsInformation IGpsLocatorControllable.TryObtainGpsInformation()
        {
            return CurrentController.CanOperate ? CurrentController.TryObtainGpsInformation() : default;
        }

    }

}
